package com.antd.common.auth.token;

import com.antd.common.auth.security.AntdUserDetails;
import com.google.common.collect.Sets;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * TODO
 *
 * @author 子丶沫
 * @version 1.0
 * @date 2020/12/2 17:49
 */
public class AntdUserAuthenticationConverter extends DefaultUserAuthenticationConverter {
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey(USERNAME)) {
            Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
            String username = (String) map.get(USERNAME);
            String userId = (String) map.get("userId");
            AntdUserDetails user = new AntdUserDetails(userId, username, "", authorities);
            return new UsernamePasswordAuthenticationToken(user, "N/A", authorities);
        }
        return null;
    }

    /**
     * 获取权限信息
     * @param map
     * @return
     */
    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        Object authorities = map.get(AUTHORITIES);
        List<LinkedHashMap> mapList= (List<LinkedHashMap>) authorities;
        Set<String> set= Sets.newHashSet();
        /**
         * 此处由于 JwtTokenStore-> JwtAccessTokenConverter->
         * protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication)方法
         * content = objectMapper.formatMap(tokenConverter.convertAccessToken(accessToken, authentication))方法
         * 此方法将登录时 Collection<SimpleGrantedAuthority> 权限集合序列化为 List<LinkedHashMap> key authority value 权限标识
         * 生成token后反解析token 获取权限值为{authority=sys:user:list}字符串
         * 导致登录成功后@PreAuthorize("hasAuthority('sys:user:list')") 无法匹配成功 ，系统提示无权限bug
         * 具体逻辑请查看@hasAuthority方法，故此处进行权限重新赋值操作，引发此问题的原因暂未找到，只能暂时如此处理
         * 以后有机会再排查
         */
        mapList.forEach(data->set.add(String.valueOf(data.get("authority"))));
        return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils
                .collectionToCommaDelimitedString(set));
    }

}
